﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.Win32.SafeHandles;

namespace Needle.Utils.Collections.Threadsafe
{
    /// <summary></summary>
    public class BlockingQueue<T> : IQueue<T> , IDisposable
    {

        private LockFreeQueue<T> _queue;
        private AutoResetEvent _itemEnqueued;
        /// <summary></summary>
        public BlockingQueue()
        {
            _queue = new LockFreeQueue<T>();
            _itemEnqueued = new AutoResetEvent(false);
        }
        /// <summary></summary>
        public SafeWaitHandle SafeWaitHandle
        {
            get { return _itemEnqueued.SafeWaitHandle; }
         
        }

        #region IQueue<T> Members
        /// <summary></summary>
        public int Count
        {
            get { return _queue.Count; }
        }
        /// <summary></summary>
        public bool TryEnqueue(T item)
        {
            Enqueue(item);
            return true;
        }
        /// <summary></summary>
        public void Enqueue(T item)
        {
            _queue.Enqueue(item);
            _itemEnqueued.Set();
        }
        /// <summary></summary>
        public bool TryDequeue(out T item)
        {
            return _queue.TryDequeue(out item);
        }
        /// <summary></summary>
        public T Dequeue()
        {
            T item = default(T);
            while (!_queue.TryDequeue(out item))
                _itemEnqueued.WaitOne();
            return item;
        }

        #endregion

        #region IDisposable Members
        /// <summary></summary>
        ~BlockingQueue()
        {
            Dispose(false);
        }
        /// <summary></summary>
        protected void Dispose(bool disposing)
        {
            _itemEnqueued.Close();
        }
        /// <summary></summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion
    }
}
